package cn.tedu._07springaop.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 切面类，将日志功能抽离(解耦)
 */
@Aspect
@Component
public class LogAspect {
    /**
     * before：前置通知
     * JoinPoint参数：连接点对象，即执行的目标方法对象
     */
//    @Before(value = "execution(public int cn.tedu._07springaop.aop.CalculatorImpl.*(..))")
//    public void beforeMethod(JoinPoint joinPoint){
//        /*
//            joinPoint.getSignature() 获取方法签名
//            joinPoint.getSignature().getName() 获取方法名
//            joinPoint.getArgs() 获取方法参数
//         */
//        String name = joinPoint.getSignature().getName();
//        String args = Arrays.toString(joinPoint.getArgs());
//        System.out.println("前置通知："+name+"方法执行，参数为"+args);
//    }

    /**
     * after：后置通知
     * 在目标方法结束(正常或非正常结束)后执行，用于收尾、释放资源等，一般最后执行
     */
//    @After(value = "execution(public int cn.tedu._07springaop.aop.CalculatorImpl.*(..))")
//    public void afterMethod(JoinPoint joinPoint){
//        String name = joinPoint.getSignature().getName();
//        System.out.println("后置通知："+name+"方法执行结束");
//
//    }

    /**
     * afterReturning：返回通知
     * 在目标方法正常结束后执行，可以获取返回值
     */
//    @AfterReturning(value = "execution(public int cn.tedu._07springaop.aop.CalculatorImpl.*(..))",
//    returning = "result")
//    public void afterReturning(JoinPoint joinPoint,Object result){
//        String name = joinPoint.getSignature().getName();
//        System.out.println("返回通知："+name+"方法执行完毕，结果为："+result);
//    }

    /**
     * afterThrowing：异常通知
     */
//    @AfterThrowing(value = "execution(public int cn.tedu._07springaop.aop.CalculatorImpl.*(..))",
//    throwing = "exception")
//    public void afterThrowing(JoinPoint joinPoint,Throwable exception){
//        String name = joinPoint.getSignature().getName();
//        System.out.println("异常通知："+name+"方法抛出异常，提示信息为："+exception.getMessage());
//    }

    /**
     * around：环绕通知，可以等效替代上述4个通知
     * ProceedingJoinPoint：过程中切入点
     */
    @Around(value = "execution(public int cn.tedu._07springaop.aop.CalculatorImpl.*(..))")
    public Object aroundMethod(ProceedingJoinPoint joinPoint){
        Object result = null;
        try {
            String name = joinPoint.getSignature().getName();
            System.out.println("前置通知："+name+"方法开始执行");
            result = joinPoint.proceed();
            System.out.println("返回通知：result = "+result);
        } catch (Throwable throwable){
            System.out.println("异常通知");
        } finally {
            System.out.println("后置通知");
        }
        return result;
    }
}
